﻿
if (typeof jQuery === 'undefined') {
    throw new Error('jquery.popup JavaScript requires jQuery');
}

if (typeof Plugin === 'undefined') {
    throw new Error('jquery.popup JavaScript requires Plugin');
}


(function ($) {
    'use strict';

    var PopupWindow = function (el, options) {
        this.$el = $(el);
        this.namespace = _config_.popupWindow.namespace;
        this.defaults = _config_.popupWindow.defaults;
        this.methods = _config_.popupWindow.methods;
        this.events = _config_.popupWindow.events;

        this.initials = $.com.getDataBindFromElement(this.$el);
        this.originals = $.extend(true, {}, this.defaults, this.initials);
        this.originals.isGrid = this.$el.find(_config_.selector.grid).hasValue();
        this.options = $.extend(true, {}, this.originals, options);
        this.options.serial = $.com.getSerial(16);
        //处理id
        this.getNamedPrefix('type');
        this.init();
    };

    PopupWindow.prototype = new Plugin();

    PopupWindow.prototype.init = function () {
        this.$form = this.$el.find(this.options.form || _config_.selector.form).first();
        //if ($.com.isJqueryObject(this.$form) && (!$.com.hasValue(this.$form.data(_config_.form.namespace)))) {
        //    this.$form.form();
        //}
        this.$grid = this.$el.find(this.options.grid || _config_.selector.grid).first();
        if ($.com.isJqueryObject(this.$grid) && (!$.com.hasValue(this.$grid.data(_config_.grid.namespace)))) {
            this.$grid.grid();
        }
        this.$selection = this.$el.find(this.options.selection || '.selection').first();
        if ($.com.isJqueryObject(this.$selection) && (!$.com.hasValue(this.$selection.data(_config_.form.namespace)))) {
            this.$selection.addClass('row').css('padding', '0 10px');
            this.$selection.form();
            this.$selection.find('div.bootstrap-tagsinput').addClass('col-md-12').width('100%');
        }
        this.options.isMultiple = typeof this.options.multiple === 'string' && this.options.multiple.startWith('multiple');
        this.options = $.extend(true, {}, _config_.popupWindow.initials, this.calculateSize(), this.options);

        this.initEvent();
        this.initPopup();
    };

    PopupWindow.prototype.initPopup = function () {
        this.execute(this.options.loading);

        //kendo ui 方式
        var that = this;
        this.options.close = function (event) {
            that.onClose(event);
        };

        this.$popup = this.$el.kendoWindow(this.options);
        this.popup = this.$el.data(this.options.role);

        this.$buttons = this.$el.find(_config_.selector.button);
        if (this.$buttons.hasValue()) {
            this.$buttons.button();
        }

        this.execute(this.options.loaded);
    };

    PopupWindow.prototype.initEvent = function () {
        var that = this;

        this.$el.off('open.' + this.namespace).on('open.' + this.namespace, function (event, options) {
            that.onOpen(event, options);
            event.stopPropagation();
        });

        this.$buttons = this.$el.find('.actions').find(_config_.selector.button);
        if ($.com.isJqueryObject(this.$buttons)) {
            this.authorizeButton();

            this.$el.off('ok.' + this.namespace).on('ok.' + this.namespace, function (event) {
                that.onOk(event);
                event.stopPropagation();
            });

            this.$el.off('close.' + this.namespace).on('close.' + this.namespace, function (event) {
                that.popup.close();
                event.stopPropagation();
            });

            this.$buttons.filter(_config_.selector.determineButton).click(function (event) {
                that.$el.trigger('ok');
                event.stopPropagation();
            });

            this.$buttons.filter(_config_.selector.closeButton).click(function (event) {
                that.$el.trigger('close');
                event.stopPropagation();
            });
        }
    };

    // popup 中存在 grid 的情况下单选和多选的处理
    PopupWindow.prototype.select = function (values, dblclick) {
        if ($.com.hasValue(values)) {
            this.options.data = values;
            if ($.com.isArray(values) && this.options.isMultiple && $.com.isJqueryObject(this.$selection)) {
                //多选模式 $selection赋值
                var $field = this.$selection.find('[role="tagsinput"]:first');
                if ($.com.hasValue($field)) {
                    for (var i = 0; i < values.length; i++) {
                        $field.tagsinput('add', values[i]);
                    }

                    this.options.data = $field.tagsinput('items');
                }
            } else {
                if (dblclick) {
                    //单选且双击, 则返回
                    this.onOk();
                }
            }
        } else {
            return this.options.data;
        }
    };

    // destroy
    PopupWindow.prototype.destroy = function () {
        this.$el.removeData(this.namespace);
        this.$el.remove();
    };

    PopupWindow.prototype.onOpen = function (event, options) {
        options = options || {};
        this.options.multiple = options.multiple || this.originals.multiple || this.options.multiple;
        this.options = $.extend(true, {}, this.calculateSize(), this.originals, options);

        //打开前, 现在前置事件只需返回 false 就可以阻止事件继续执行
        var ret = this.execute(this.options.opening, event);
        if ($.com.hasValue(ret) && ret === false) {
            return;
        }

        //重新计算 input 和 formData 的值
        $.com.getFromPopupParameter(this.options);

        this.popup.setOptions(this.options);
        this.popup.center().open();

        var $content = this.$el.find('.popupContent');
        $content.removeClass('multiple');
        if (this.options.isGrid) {
            if (this.options.isMultiple) {
                this.$selection.show();
                $content.addClass('multiple');
            } else {
                this.$selection.hide();
            }
        } else {
            $content.addClass('multiple');
        }

        this.reselection();

        if ($.com.isJqueryObject(this.$form)) {
            var form = this.$form.data(_config_.form.namespace);
            form.reset();

            form.refresh(this.options.formData, true);
            //打开后取消form中的验证
            form.validate(false);

            if (form.options.isEdit) {
                form.$buttons.filter('[data-button="post"]').button('display', false);
                form.$buttons.filter('[data-button="put"],[data-button="delete"]').button('display', true);
            } else {
                form.$buttons.filter('[data-button="post"]').button('display', true);
                form.$buttons.filter('[data-button="put"],[data-button="delete"]').button('display', false);
            }

            //执行查询
            var $queryButton = form.$buttons.filter(_config_.selector.queryButton);
            if ($.com.isJqueryObject($queryButton)) {
                form.getQueryExpression();
                if ($.com.isJqueryObject(this.$grid)) {
                    var grid = this.$grid.data(_config_.grid.namespace);
                    var dataSource = $.com.getDataSource(grid.role);
                    dataSource = $.com.getQueryOptions(dataSource, form.options.dataSource);
                    if ($.com.hasValue(dataSource)) {
                        dataSource.page = 1;
                        dataSource.autoQuery = true;

                        //TBC ***** 使用 setOptions 给 dataSource 设置值, 就会导致 grid 记住了上次查询的条件
                        //grid.role.setOptions({ selectable: this.options.multiple, dataSource: dataSource });
                        //TBC ***** 使用 dataSource.query 会导致点击刷新和翻页时丢失过滤区的条件
                        grid.role.dataSource.options.transport = dataSource.transport;
                        grid.role.dataSource.options.autoQuery = false;
                        grid.role.setOptions({ selectable: this.options.multiple });
                        grid.role.dataSource.options.autoQuery = true;
                        grid.role.dataSource.query(dataSource);

                        grid.resize();
                        grid.initEvent();
                    }
                } else {
                    $queryButton.click();
                }
            }
        }

        //成功打开后
        this.execute(this.options.opened, event);
    };

    // popupWindow on search event
    PopupWindow.prototype.onOk = function (event) {
        //关闭前
        if (this.options.isMultiple) {
            this.options.data = this.$selection.find('[role="tagsinput"]:first').tagsinput('items') || [];
        }

        //现在前置事件只需返回 false 就可以阻止事件继续执行
        var ret = this.execute(this.options.closing, event);
        if ($.com.hasValue(ret) && ret === false) {
            return;
        }
        ret = this.execute(this.options.confirming, event);
        if ($.com.hasValue(ret) && ret === false) {
            return;
        }

        //var data = $.extend(true, [], this.options.data);
        var data = $.com.cleanData(this.options.data) || [];

        // TBC ***** 此处待验证, 是否可所有情况均按对象方式处理
        if ($.com.hasValue(this.options.inout) && $.com.hasValue(this.options.openerProperty)) {
            var d = {};
            var formData = $.com.getFormData(this.options.opener);
            if ($.com.hasValue(formData)) {
                if (this.options.isMultiple) {
                    formData[this.options.openerProperty] = data;
                } else if ($.com.isArray(data)) {
                    formData[this.options.openerProperty] = data[0];
                } else {
                    delete formData[this.options.openerProperty];
                }

                var prefix = this.options.opener.attr(_config_.default.parameterPrefix) || _config_.default.parameterPrefixValue;
                for (var key in this.options.inout) {
                    var value = this.options.inout[key];
                    if (typeof value === 'string' && !value.startWith(prefix)) {
                        if ($.com.isArray(data)) {
                            d[value] = data.select(key).join(', ');
                        } else {
                            delete formData[value];
                        }
                    }
                }
            }

            formData = $.extend(formData, d);
            this.options.opener.form('refresh', formData, true);
        } else if ($.com.isArray(this.options.parameter)) {
            var $opener = $(this.options.opener);
            var outs = this.options.parameter.where(function (x) { return x.transfer.includes('out'); });
            if ($.com.isJqueryObject($opener) && $.com.isArray(outs)) {
                for (var i = 0; i < outs.length; i++) {
                    var x = outs[i];
                    if ($.com.hasValue(x.target) && $.com.hasValue(x.source)) {
                        var targets = data.select(x.target);
                        if ($.com.isArray(targets)) {
                            x.value = targets.length === 1 ? targets[0] : targets.join(', ');
                        } else {
                            x.value = null;
                        }

                        var $el = $opener.find('[' + _config_.attribute.input + '="' + x.source + '"]');
                        if ($.com.isJqueryObject($el)) {
                            var input = $el.data(_config_.input.namespace);
                            if ($.com.hasValue(input)) {
                                input.refresh(x.value, true);
                                if ($el.is('span,label,a')) {
                                    input.writeBack();
                                } else {
                                    $el.change();
                                }
                            } else {
                                if ($el.is('span,label,a')) {
                                    $el.html(x.value);
                                } else {
                                    $el.val(x.value).change();
                                }
                            }
                        }
                    }
                }
            }
        }

        this.popup.close();
        //关闭后
        this.execute(this.options.confirmed, event);
        this.execute(this.options.closed, event);
    };

    // popupWindow on search event
    PopupWindow.prototype.onClose = function (event) {
        //关闭前
        this.execute(this.options.closing, event);

        //this.popup.close();

        //关闭后
        this.execute(this.options.closed, event);
    };

    PopupWindow.prototype.calculateSize = function () {
        this.options.size = this.options.size || 'default';
        if (this.options.isGrid) {
            this.options.isMultiple = typeof this.options.multiple === 'string' && this.options.multiple.startWith('multiple');
            if (this.options.isMultiple) {
                this.options.size = 'multiple';
            } else {
                this.options.size = 'single';
            }
        }

        var size = _config_.popupWindow.size[this.options.size];
        size.isMultiple = this.options.isMultiple;
        return size;
    };

    PopupWindow.prototype.reselection = function () {
        if ($.com.isJqueryObject(this.$selection)) {
            //this.$selection.css('display', 'grid');
            var $field = this.$selection.find('[role="tagsinput"]:first');
            if ($.com.isJqueryObject($field)) {
                var data = $.extend(true, [], this.options.data);
                $field.tagsinput('removeAll');
                this.select(data);
            }
        }

        this.options.data = [];
    };

    // plug-in
    $.fn.popupWindow = function (options) {
        var args = Array.prototype.slice.call(arguments, 1);
        var value = undefined;
        this.each(function () {
            var $this = $(this);
            var data = $this.data(_config_.popupWindow.namespace);
            // initial if nover
            if ($.com.isNullOrEmpty(data)) {
                data = new PopupWindow(this, typeof options === 'object' && options);
                $this.data(_config_.popupWindow.namespace, data);
            }

            if (typeof options === 'string') {
                //if options is not a method
                if ($.inArray(options, data.methods) < 0) {
                    throw 'Unknown method: ' + options;
                }

                //if options is a plugin method, to execute
                value = data[options].apply(data, args);
            }
        });

        return typeof value === 'undefined' ? this : value;
    };
})(jQuery);

(function ($) {
    'use strict';

    var Popup = function (el, options) {
        this.$el = $(el);
        this.namespace = _config_.popup.namespace;
        this.defaults = _config_.popup.defaults;
        this.methods = _config_.popup.methods;
        this.events = _config_.popup.events;
        this.initials = $.com.getDataBindFromElement(this.$el);
        this.originals = $.extend(true, {}, this.defaults, this.initials);
        this.options = $.extend(true, {}, this.originals, options);
        this.originals.serial = $.com.getSerial(16);
        this.init(options);
    };

    Popup.prototype = new Plugin();

    Popup.prototype.init = function () {
        this.$popup = $(this.originals.popup);
        if (!$.com.isJqueryObject(this.$popup)) {
            this.$popup = $('[data-type="' + this.originals.popup + '"]');
        }

        this.$form = this.$el.parents(_config_.selector.form).first();
        if (!this.$el.isBelongToForm(this.$form)) {
            this.$form = $(_config_.selector.default);
        }

        this.initEvent();
    };

    Popup.prototype.initEvent = function () {
        var that = this;
        this.$el.off('open.' + this.namespace).on('open.' + this.namespace, function (event, options) {
            that.onOpen(event, options);
        });

        if ($.com.hasValue(this.options.field) && this.$el.is('[data-icon]')) {
            if (!$.com.isJqueryObject(this.$fieldset)) {
                this.$fieldset = this.$el.input('getValue', '$fieldset');
            }

            if ($.com.isJqueryObject(this.$fieldset)) {
                var $icon = this.$fieldset.find('.input-group-addon');
                $icon.css('cursor', 'pointer').click(function (event) {
                    that.trigger(event, 'open');
                });
            }
        } else {
            this.$el.click(function (event) {
                that.trigger(event, 'open');
            });
        }
    };

    /*
    *   popupParameter 属性, 有以下属性
    *   opener: undefined,                                  //打开者 / 接收者, 默认取当前组件所在form;
    *   openerProperty: undefined,                          //指示接收者接收的属性;
    *   inout: []                                           //这个参数是原来 parameter 参数的简写形式, 由左侧 in 属性名 = 右侧 out 属性名/值来构成; 如果无此参数, 则默认用当前元素构造出来
    */
    Popup.prototype.onOpen = function () {
        //弹出框可触发弹出事件的前提是: 1. popup属性指定的元素存在, 2. enable 属性为 true 且 editable 为 false(为 true 时, 不可触发事件)
        if ($.com.isJqueryObject(this.$popup) && this.isTrue('enable') && !this.isTrue('editable')) {

            this.options.popupParameter = $.extend(true, {}, this.originals.popupParameter);

            //1. 获取 opener
            var opener = $(this.options.popupParameter.opener || _config_.selector.default);
            this.options.popupParameter.opener = $.com.isJqueryObject(opener) ? opener : this.$form;
            if (!$.com.isJqueryObject(this.options.popupParameter.opener)) {
                this.options.popupParameter.opener = $.com.isJqueryObject(this.$el.children(_config_.selector.input)) ? this.$el : this.$el.parent();
            }

            if (!$.com.isArray(this.options.popupParameter.parameter) && !$.com.hasValue(this.options.popupParameter.inout)) {
                var source = this.options.source || this.options.field || 'Name';
                var target = this.options.target || this.options.field || 'Name';
                this.options.popupParameter.parameter = [{ transfer: 'out', source: source, target: target }];
                //this.options.popupParameter.inout = {};
                //this.options.popupParameter.inout[target] = source;
            }

            $.com.getPopupParameterValue(this.options.popupParameter);

            //传入参数为: popupParameter:{opener, parameter}, 其余参数现在放在 opening 之后获取
            this.$popup.filter('[id]').first().trigger('open', [this.options.popupParameter]);
        }
    };

    // plug-in
    $.fn.popup = function (options) {
        var args = Array.prototype.slice.call(arguments, 1);
        var value = undefined;
        this.each(function () {
            var $this = $(this);
            var data = $this.data(_config_.popup.namespace);
            // initial if nover
            if ($.com.isNullOrEmpty(data)) {
                data = new Popup(this, typeof options === 'object' && options);
                $this.data(_config_.popup.namespace, data);
            }

            if (typeof options === 'string') {
                //if options is not a method
                if ($.inArray(options, data.methods) < 0) {
                    throw 'Unknown method: ' + options;
                }

                //if options is a plugin method, to execute
                value = data[options].apply(data, args);
            }
        });

        return typeof value === 'undefined' ? this : value;
    };
})(jQuery);